/**
 * 
 */
package org.gas.barapraja.proc;

import java.io.IOException;

import org.apache.log4j.Logger;

import com.logica.smpp.Connection;
import com.logica.smpp.Data;
import com.logica.smpp.SmppObject;
import com.logica.smpp.TCPIPConnection;

/**
 * @author gilang
 *
 */
public class GasSmscListener extends SmppObject implements Runnable {
	
	private static final Logger logger=Logger.getLogger(GasSmscListener.class);

	private Connection serverCon;
	
	private int port;
	
	private boolean asynchronous=false;
	
	private boolean keepReceiving=true;
	
	private boolean isReceiving=false;
	
	private long acceptTimeOut=Data.ACCEPT_TIMEOUT;
	
	private ProcessorFactory processorFactory;
	
	/**
	 * 
	 * @param port
	 */
	public GasSmscListener(int port) {
		this.port=port;
		this.processorFactory=PduProccesorFactory.getFactory();
	}
	
	/**
	 * 
	 * @param port
	 * @param async
	 */
	public GasSmscListener(int port,boolean async){
		this.port=port;
		this.asynchronous=async;
		this.processorFactory=PduProccesorFactory.getFactory();
	}
	
	public synchronized void startListener() throws IOException{
		logger.info("starting listener on port: "+port);
		if(!isReceiving){
			serverCon=new TCPIPConnection(port);
			serverCon.setReceiveTimeout(getAcceptTimeOut());
			serverCon.open();
			keepReceiving=true;
			if(asynchronous){
				Thread thread=new Thread(this);
				thread.start();
				logger.info("started new thread");
			}else{
				logger.info("starting single thread");
				run();
			}
		}else{
			logger.info("already receiving");
		}
		
	}
	
	public synchronized void stopListener() throws IOException{
		keepReceiving=false;
		while(isReceiving){
			Thread.yield();
		}
		serverCon.close();
	}
	
	/* (non-Javadoc)
	 * @see java.lang.Runnable#run()
	 */
	@Override
	public void run() {
		isReceiving=false;
		try{
			while(keepReceiving){
				listen();
				Thread.yield();
			}
		}catch (IOException e) {
			e.printStackTrace();
		}finally{
			isReceiving=false;
		}
		
	}
	
	protected void listen() throws IOException{
		Connection connection=null;
		serverCon.setReceiveTimeout(getAcceptTimeOut());
		connection=serverCon.accept();
		if(connection!=null){
			logger.info("accepted connection at port:"+port);
			GasSmscSession session=new GasSmscSession(connection);
			PduProcessor processor=processorFactory.createPduProcessor(session);
			ProccessContainer container=PduProcessorContainer.getContainerInstance();
			container.addProcessor(processor);
			Thread thread=new Thread(session);
			thread.start();
		}else{
			keepReceiving=false;
		}
	}

	/**
	 * @return the acceptTimeOut
	 */
	public long getAcceptTimeOut() {
		return acceptTimeOut;
	}

	/**
	 * @param acceptTimeOut the acceptTimeOut to set
	 */
	public void setAcceptTimeOut(long acceptTimeOut) {
		this.acceptTimeOut = acceptTimeOut;
	}

	
}
